import { ZCP } from "./zcp";
import { Inject } from "inject-provide";

import * as fse from "fs-extra";
import * as path from "path";

export class App {
	constructor(@Inject(ZCP) public zcp: ZCP) {}

	traveral(arr: number[], size: number): Array<number[]> {
		const cards: Array<number[]> = [];

		(function traveral(arr: number[], size: number, result: number[]) {
			const arrconcat = (arr: Array<number[]>): number[] => {
				const result: number[] = [];
				arr.forEach(e => {
					e.forEach(v => {
						result.push(v);
					});
				});
				return result;
			};

			if (size > arr.length) {
				return;
			} else if (size === arr.length) {
				cards.push(arrconcat([result, arr]));
			} else {
				for (let i = 0; i < arr.length; i++) {
					const temp = arrconcat([result]);
					temp.push(arr[i]);
					if (size === 1) {
						cards.push(temp);
					} else {
						const tempArr = arrconcat([arr]);
						tempArr.splice(0, i + 1);
						traveral(tempArr, size - 1, temp);
					}
				}
			}
		})(arr, size, []);
		return cards;
	}

	write(filePath: string, data: string) {
		const abFilePath = path.resolve(process.cwd(), filePath);
		fse.ensureFileSync(abFilePath);
		fse.writeFileSync(abFilePath, data);
	}

	canGetCards(bestSolution: [number[], number[]]) {
		return bestSolution !== undefined && bestSolution.length > 0
			? bestSolution[0].length + bestSolution[1].length
			: 0;
	}

	checkCardCut(bestSolution: [number[], number[]]) {
		if (bestSolution === undefined || bestSolution.length < 2) {
			return null;
		}

		return this.zcp.sum(bestSolution[0]) - this.zcp.sum(bestSolution[1]);
	}

	diffDards(filePath: string, arr: number[], size: number) {
		let minNum = -1;
		const data = {
			"0": 0,
			"1": 0,
			"2": 0,
			"3": 0,
			"4": 0,
			distribution: [] as number[]
		};
		const result = this.traveral(arr, size);

		result.forEach(v => {
			const bestSolution = this.zcp.when(v)[0];
			const canGetCards = this.canGetCards(bestSolution);

			if (minNum < 0) {
				minNum = canGetCards;
			}

			if (canGetCards < minNum) {
				minNum = canGetCards;
			}

			const dataItem = {
				cards: v,
				solution: bestSolution
			};

			if ((data as any)[canGetCards.toString()] !== undefined) {
				(data as any)[canGetCards.toString()]++;
			} 
			data.distribution.push(canGetCards);
		});

		console.log(`共有${data.distribution.length}种情况`);
		console.log(`张昌蒲${size}张牌情况下，最差获得牌数：${minNum}`);

		this.write(filePath, JSON.stringify(data));
	}

	hasSameCards(filePath: string, arr: number[], size: number) {
		const diffCards = size - 2;

		let minNum = -1;
		const data: any[] = [];
		const result = this.traveral(arr, diffCards);

		result.forEach(v => {
			for (let sameCardIndex = 1; sameCardIndex <= 13; sameCardIndex++) {
				let bestSolution = this.zcp.when(v, sameCardIndex)[0];

				if (this.checkCardCut(bestSolution) !== null) {
					if (this.checkCardCut(bestSolution) === 0) {
						bestSolution = [
							bestSolution[0].concat(sameCardIndex),
							bestSolution[1].concat(sameCardIndex)
						];
					} else if (this.checkCardCut(bestSolution) === sameCardIndex) {
						bestSolution = [
							bestSolution[0],
							bestSolution[1].concat(sameCardIndex)
						];
					} else if (this.checkCardCut(bestSolution) === -1 * sameCardIndex) {
						bestSolution = [
							bestSolution[0].concat(sameCardIndex),
							bestSolution[1]
						];
					} else if (this.checkCardCut(bestSolution) === 2 * sameCardIndex) {
						bestSolution = [
							bestSolution[0],
							bestSolution[1].concat([sameCardIndex, sameCardIndex])
						];
					} else if (this.checkCardCut(bestSolution) === -2 * sameCardIndex) {
						bestSolution = [
							bestSolution[0].concat([sameCardIndex, sameCardIndex]),
							bestSolution[1]
						];
					}
				} else {
					bestSolution = [[sameCardIndex], [sameCardIndex]];
				}

				const canGetCards = this.canGetCards(bestSolution);

				if (minNum < 0) {
					minNum = canGetCards;
				}

				if (canGetCards < minNum) {
					minNum = canGetCards;
				}

				const dataItem = {
					cards: v.concat([sameCardIndex, sameCardIndex]),
					solution: bestSolution
				};

				data.push(dataItem);
			}
		});

		console.log(`在有2张相同牌的情况下，共有${data.length}种情况`);
		console.log(
			`张昌蒲${size}张牌，且有2张相同牌的情况下，最差获得牌数：${minNum}`
		);

		this.write(filePath, JSON.stringify(data, null, "\t"));
	}

	// exchange(arr1: number[][], arr2: number[][]) {
	// 	const result: number[][] = [];
	// 	const subArr = arr1.length < arr2.length ? arr1 : arr2;
	// 	const mainArr = arr1.length >= arr2.length ? arr1 : arr2;

	// 	for (let i in mainArr) {
	// 		for (let j in subArr) {
	// 			const newItem = mainArr[i].concat(subArr[j]);
	// 			result.push(newItem);
	// 		}
	// 	}

	// 	return result;
	// }
}
